/******************************************************************************/
/*!

\file   Vector.inl
\author M.J. Gardner
\date   12/3/2011
\brief
    Templated vector math library. See Vector.hpp for details.

*/
/******************************************************************************/
#include <algorithm>  //min
#include <cmath>      //sqrt, pow

namespace Vec
{
////////////////////////////////////////////////////////////////////////////////
////////////////////////////////////////////////////////////////////////////////
/*
  Vector implementation
  (iterator functions are waaaaaaaaaay below)
*/
////////////////////////////////////////////////////////////////////////////////
////////////////////////////////////////////////////////////////////////////////

  template<unsigned int N, typename T>
  Vector<N, T>::Vector(void)
  {
    _elems.fill(0);
  }

  template<unsigned int N, typename T>
  Vector<N, T>::Vector(std::initializer_list<T> list)
  {
    unsigned i = 0;
    for(typename std::initializer_list<T>::iterator it = list.begin(); it !=list.end(); ++it)
    {
      _elems.at(i) = *it;
      ++i;
      if(i >= N)
        return;
    }
  }

  template<unsigned int N, typename T>
  Vector<N, T>::Vector(T *rhs)
  {
    _elems.fill(0);
    for(unsigned int i = 0; i < N; ++i)
      _elems.at(i) = rhs[i];
  }

  template<unsigned int N, typename T>
  Vector<N, T>::Vector(const typename std::array<T, N>::iterator &begin,
                        const typename std::array<T, N>::iterator &end)
  {
    unsigned int i = 0;
    for(typename std::array<T, N>::iterator it = begin; it != end; ++it)
    {
      _elems.at(i) = *it;
      ++i;
    }
  }

  template<unsigned int N, typename T>
  Vector<N, T>::Vector(std::array<T, N> &rhs)
  {
    VEC_IT elem_it = Begin();
    VEC_IT elem_end = End();
    typename std::array<T, N>::iterator it = rhs.begin();
    typename std::array<T, N>::iterator end = rhs.end();
    while ((it != end) && (elem_it != elem_end))
    {
      *elem_it = *it;
      ++it;
      ++elem_it;
    }
  }

  //if rhs and this have the same dimension, simply copy over all elements from rhs.
  //if rhs is lower dimensional, copy all elements from rhs and fill the rest with 0.
  //if this is lower dimensional, copy over the first N elements of rhs and ignore the rest.
  template<unsigned int N, typename T>
  Vector<N, T>::Vector(const Vector &rhs)
  {
    CopyElems(rhs);
  }

  template<unsigned int N, typename T>
  Vector<N, T>::~Vector()
  {
  }



/******************************************************************************/
/*!
  \brief
    assignment operator.
    If rhs and this have the same dimension, simply assigns all elements equal
    to the corresponding elements from rhs.
    If rhs is lower dimensional than this, assigns the first (dimension of rhs)
    elements equal to the corresponding elements from rhs and sets the rest to 0.
    If rhs is higher dimensional than this, assigns all elements equal to the
    corresponding elements from rhs, and ignores all beyond the Nth element of rhs.

  \param  rhs
    an existing vector that this one will be equal to after assignment

  \return
    reference to this, so assignment-chaining is possible
*/
/******************************************************************************/
  template<unsigned int N, typename T>
  Vector<N, T> &Vector<N, T>::operator=(const Vector &rhs)
  {
    if (*this != rhs)
    {
      _elems.fill(0);
      CopyElems(rhs);
    }
    return *this;
  }


/******************************************************************************/
/*!
  \brief
    scalar multiplication and assignment combo. Multiplies all elements by the
    scalar parameter.

  \param  rhs
    each element of this vector will be multiplied by rhs

  \return
    reference to this, so assignment-chaining is possible
*/
/******************************************************************************/
  template<unsigned int N, typename T>
  Vector<N, T> &Vector<N, T>::operator*=(const T rhs)
  {
    for(unsigned i = 0; i < _elems.size(); ++i)
      _elems.at(i) *= rhs;

    return *this;
  }


/******************************************************************************/
/*!
  \brief
    Scalar division and assignment. Divides all elements by the scalar parameter.

  \param  rhs
    each element of this vector will be divided by rhs

  \return
    reference to this, so assignment-chaining is possible
*/
/******************************************************************************/
  template<unsigned int N, typename T>
  Vector<N, T> &Vector<N, T>::operator/=(const T rhs)
  {
      *this *= 1 / rhs;
      return *this;
  }


/******************************************************************************/
/*!
  \brief
    Vector addition and assignment. Adds the corresponding element of rhs to each
    element of this.

  \param  rhs
    the vector to add to this one

  \return
    reference to this, so assignment-chaining is possible
*/
/******************************************************************************/
  template<unsigned int N, typename T>
  Vector<N, T> &Vector<N, T>::operator+=(const Vector<N, T> &rhs)
  {
    for(unsigned i = 0; i < _elems.size(); ++i)
      _elems.at(i) += rhs._elems.at(i);

    return *this;
  }


/******************************************************************************/
/*!
  \brief
    Vector subtraction and assignment. Subtracts the corresponding element of rhs
    to each element of this.

  \param  rhs
    the vector to subtract from this one

  \return
    reference to this, so assignment-chaining is possible
*/
/******************************************************************************/
  template<unsigned int N, typename T>
  Vector<N, T> &Vector<N, T>::operator-=(const Vector<N, T> &rhs)
  {
    *this += -rhs;
    return *this;
  }


/******************************************************************************/
/*!
  \brief
    unary negation. negates each element of this and returns the result.
    does not change this vector itself.

  \return
    a negated version of this vector
*/
/******************************************************************************/
  template<unsigned int N, typename T>
  Vector<N, T> Vector<N, T>::operator-(void) const
  {
    Vector<N, T> negated(*this);
    for(unsigned i = 0; i < negated._elems.size(); ++i)
      negated._elems.at(i) = -(negated._elems.at(i));
    return negated;
  }


/******************************************************************************/
/*!
  \brief
    equality operator. Compares each element of lhs and rhs for equality.

  \param  lhs
    one of the vectors to compare

  \param  rhs
    the other vector to compare

  \return
    are the vectors equal? (equivalently, is each element of the vectors equal)
*/
/******************************************************************************/
  template<unsigned int N, typename T>
  bool operator==(const Vector<N, T> &lhs, const Vector<N, T> &rhs)
  {
    for(unsigned i = 0; i < N; ++i)
    {
      if(abs(lhs[i] - rhs[i]) > EPSILON)
        return false;
    }
    return true;
  }


/******************************************************************************/
/*!
  \brief
    inequality operator. Always has the opposite result from operator==

  \param  lhs
    one of the vectors to compare

  \param rhs
    the other vector to compare

  \return
    are the vectors inequal? (negation of the result of operator==)
*/
/******************************************************************************/
  template<unsigned int N, typename T>
  bool operator!=(const Vector<N, T> &lhs, const Vector<N, T> &rhs)
  {
    return !(lhs == rhs);
  }


/******************************************************************************/
/*!
  \brief
    vector addition. Adds 2 vectors elementwise.

  \param  lhs
    one of the vectors to add

  \param  rhs
    the other vector to add

  \return
    sum of the vectors. each element is the sum of the corresponding elements in
    lhs and rhs (i.e. ret[i] = lhs[i] + rhs[i])
*/
/******************************************************************************/
  template<unsigned int N, typename T>
  Vector<N, T> operator+(const Vector<N, T> &lhs, const Vector<N, T> &rhs)
  {
    Vector<N, T> sum(lhs);
    sum += rhs;
    return sum;
  }

/******************************************************************************/
/*!
  \brief
    vector subtraction. Subtracts rhs from lhs elementwise.

  \param  lhs
    starting vector

  \param  rhs
    the vector to subtract from lhs

  \return
    difference of the vectors. Each element is the difference of the corresponding
    elements in lhs and rhs (i.e. ret[i] = lhs[i] - rhs[i])
*/
/******************************************************************************/
  template<unsigned int N, typename T>
  Vector<N, T> operator-(const Vector<N, T> &lhs, const Vector<N, T> &rhs)
  {
    return lhs + (-rhs);
  }


/******************************************************************************/
/*!
  \brief
    scalar multiplication with the vector on the left-hand side

  \param  lhs
    the vector to scale

  \param  rhs
    the scalar to multiply by

  \return
    scaled version of lhs
*/
/******************************************************************************/
  template<unsigned int N, typename T>
  Vector<N, T> operator*(const Vector<N, T> &lhs, const T rhs)
  {
    Vector<N, T> product(lhs);
    product *= rhs;
    return product;
  }

/******************************************************************************/
/*!
  \brief
    scalar multiplication with the vector on the right-hand side

  \param  lhs
    the scalar to multiply by

  \param  rhs
    the vector to scale

  \return
    scaled version of rhs
*/
/******************************************************************************/
  template<unsigned int N, typename T>
  Vector<N, T> operator*(const T lhs, const Vector<N, T> &rhs)
  {
    return rhs * lhs;
  }

/******************************************************************************/
/*!
  \brief
    scalar division

  \param  lhs
    the vector

  \param  rhs
    scalar to divide each element of the vector by

  \return
    scaled version of lhs
*/
/******************************************************************************/
  template<unsigned int N, typename T>
  Vector<N, T> operator/(const Vector<N, T> &lhs, const T rhs)
  {
    return lhs * (1 / rhs);
  }



/******************************************************************************/
/*!
  \brief
    Dot product operation. Identical to InnerProduct.

  \param  lhs
    one of the vectors to dot

  \param  rhs
    the vector to dot with lhs

  \return
    scalar product of lhs and rhs
*/
/******************************************************************************/
  template<unsigned int N, typename T>
  T operator*(const Vector<N, T> &lhs, const Vector<N, T> &rhs)
  {
    T scalar_product = 0;
    for(unsigned i = 0; i < N; ++i)
      scalar_product += (lhs[i] * rhs[i]);

    return scalar_product;
  }


/******************************************************************************/
/*!
  \brief
    Inner product of 2 vectors. Since n-dimensional vectors reside in Euclidean
    vector spaces, this is just the familiar dot product operation

  \param  lhs
    one of the vectors to dot

  \param rhs
    the vector to dot with lhs

  \return
    scalar product of lhs and rhs
*/
/******************************************************************************/
  template<unsigned int N, typename T>
  T InnerProduct(const Vector<N, T> &lhs, const Vector<N, T> &rhs)
  {
    return lhs * rhs;
  }


/******************************************************************************/
/*!
  \brief
    find the scalar distance between 2 vectors, aka the magnitude of the vector
    from one to the other.
    Use DistanceSquared instead if you only want to compare distances.

  \param  lhs
    starting point for calculating distance

  \param  rhs
    ending point for calculating distance

  \return
    the distance from lhs to rhs
*/
/******************************************************************************/
  template<unsigned int N, typename T>
  T Distance(const Vector<N, T> &lhs, const Vector<N, T> &rhs)
  {
    return Magnitude(rhs - lhs);
  }


/******************************************************************************/
/*!
  \brief
    The squared distance between lhs and rhs. Cheaper than Distance() because it
    doesn't require sqrt(), so use this if you just need to compare 2 distances.

  \param  lhs
    starting point for calculating distance

  \param  rhs
    ending point for calculating distance

  \return
    the squared distance between lhs and rhs
*/
/******************************************************************************/
  template<unsigned int N, typename T>
  T DistanceSquared(const Vector<N, T> &lhs, const Vector<N, T> &rhs)
  {
    return MagnitudeSquared(rhs - lhs);
  }


/******************************************************************************/
/*!
  \brief
    Find the magnitude (aka length) of a vector.
    Use MagnitudeSquared instead if you only want to compare magnitudes.

  \param  vec
    the vector whose magnitude we want

  \return
    magnitude of the vector
*/
/******************************************************************************/
  template<unsigned int N, typename T>
  T Magnitude(const Vector<N, T> &vec)
  {
    return sqrt(MagnitudeSquared(vec));
  }


/******************************************************************************/
/*!
  \brief
    Find the squared magnitude of a vector. Cheaper than Magnitude because sqrt
    is not called. Use this if you just want to compare magnitudes.

  \param  vec
    the vector whose squared magnitude we are interested in

  \return
    squared magnitude of the vector
*/
/******************************************************************************/
  template<unsigned int N, typename T>
  T MagnitudeSquared(const Vector<N, T> &vec)
  {
    T square_magnitude = 0;
    for(unsigned int i = 0; i < N; ++i)
      square_magnitude += pow(vec[i], 2);
    return square_magnitude;
  }


/******************************************************************************/
/*!
  \brief
    Find a normalized version of a vector. That is, a vector with the same
    direction, but length 1.

  \param  vec
    the vector we want a normalized version of

  \return
    a normalized vector with the same direction as the argument
*/
/******************************************************************************/
  template<unsigned int N, typename T>
  Vector<N, T> Normalized(const Vector<N, T> &vec)
  {
    Vector<N, T> normal(vec);
    normal.Normalize();
    return normal;
  }



/******************************************************************************/
/*!
  \brief
    Get the dimension of a vector. In other words, its number of elements, which
    is the same as the template argument N

  \param  vec
    a vector whose dimension we want to find

  \return
    the dimension of the vector
*/
/******************************************************************************/
  template<unsigned int N, typename T>
  unsigned int Dimension(const Vector<N, T> &/*vec*/)
  {
    return N;
  }



/******************************************************************************/
/*!
  \brief
    cross product operation. Only exists in 3 and 7 dimensions. Only the
    3-dimensional version is implemented here. This is the right-handed version,
    so if you're working in a left-handed system, be sure to switch the order of
    the arguments.
    Remember that order will affect the direction of the resulting vector, and
    make sure both arguments are 3-dimensional.

  \param  lhs
    The first vector for the cross product operation. Order matters!
    Must have dimension 3.

  \param  rhs
    the second vector for the cross product operation. Order matters!
    Must have dimension 3.

  \return
    the vector product lhs x rhs
*/
/******************************************************************************/
  template<typename T>
  Vector<3, T> CrossProduct(const Vector<3, T> &lhs, const Vector<3, T> &rhs)
  {
    Vector<3, T> i({1, 0, 0});
    Vector<3, T> j({0, 1, 0});
    Vector<3, T> k({0, 0, 1});
    i *= (lhs[1] * rhs[2] - lhs[2] * rhs[1]);
    j *= (lhs[2] * rhs[0] - lhs[0] * rhs[2]);
    k *= (lhs[0] * rhs[1] - lhs[1] * rhs[0]);
    i += j;
    i += k;
    return i;
  }



/******************************************************************************/
/*!
  \brief
    Normalize a vector in place. This version, which is a member of Vector,
    changes the contents of the vector it is called on to be normalized, rather
    than returning a normalized version like the non-member function Normalized()
*/
/******************************************************************************/
  template<unsigned int N, typename T>
  void Vector<N, T>::Normalize(void)
  {
    T mag = Magnitude(*this);
    if (mag)
      return;

    *this /= Magnitude(*this);
  }

/******************************************************************************/
/*!
  \brief
    subscript operator for accessing elements of a vector

  \param  index
    index into the vector. Works the same as indexing into an array.

  \return
    the element of the vector at the specified index.
*/
/******************************************************************************/
  template<unsigned int N, typename T>
  const T &Vector<N, T>::operator[](const unsigned int index) const
  {
    return _elems.at(index);
  }
/******************************************************************************/
/*!
  \brief
    subscript operator for accessing elements of a vector (const version)

  \param  index
    index into the vector. Works the same as indexing into an array.

  \return
    the element of the vector at the specified index (const).
*/
/******************************************************************************/
  template<unsigned int N, typename T>
  T &Vector<N, T>::operator[](const unsigned int index)
  {
    return _elems.at(index);
  }



/******************************************************************************/
/*!
  \brief
    get beginning iterator of the vector

  \return
    iterator to the first element of the vector
*/
/******************************************************************************/
  template<unsigned int N, typename T>
  typename Vector<N, T>::Iterator Vector<N, T>::Begin(void)
  {
    return VEC_IT(_elems.begin());
  }


/******************************************************************************/
/*!
  \brief
    get ending iterator of the vector

  \return
    iterator to one-past-last element of the vector
*/
/******************************************************************************/
  template<unsigned int N, typename T>
  typename Vector<N, T>::Iterator Vector<N, T>::End(void)
  {
    return VEC_IT(_elems.end());
  }




/******************************************************************************/
/*!
  \brief
    output operator, for printing all the vector's elements to a stream

  \param  out
    the stream to output the vector to

  \param  vec
    the vector we want to print out

  \return
    the stream after output, so we can do output-chaining.
*/
/******************************************************************************/
  template<unsigned int N, typename T>
  std::ostream &operator<<(std::ostream &out, const Vector<N, T> &vec)
  {
    out << "< ";
    for(unsigned i = 0; i < N-1; ++i)
      out << vec[i] << ", ";
    out << vec[N-1] << " >" << std::endl;
    return out;
  }



/******************************************************************************/
/*!
  \brief
    If rhs and this have the same dimension, simply assigns all elements equal
    to the corresponding elements from rhs.
    If rhs is lower dimensional than this, assigns the first (dimension of rhs)
    elements equal to the corresponding elements from rhs and sets the rest to 0.
    If rhs is higher dimensional than this, assigns all elements equal to the
    corresponding elements from rhs, and ignores all beyond the Nth element of rhs.

  \param  rhs
    an existing vector to set the elements of this one equal to

*/
/******************************************************************************/
  template<unsigned int N, typename T>
  void Vector<N, T>::CopyElems(const Vector &rhs)
  {
    unsigned lower_dim = std::min(N, Dimension(rhs));

    for(unsigned i = 0; i < lower_dim; ++i)
      (*this)[i] = rhs[i];
  }










////////////////////////////////////////////////////////////////////////////////
////////////////////////////////////////////////////////////////////////////////
/*
  Vector Iterator implementation starts here
*/
////////////////////////////////////////////////////////////////////////////////
////////////////////////////////////////////////////////////////////////////////
  template<unsigned int N, typename T>
  Vector<N, T>::Iterator::Iterator(const typename std::array<T, N>::Iterator &it)
  : _elem_it(it)
  {
  }

  template<unsigned int N, typename T>
  Vector<N, T>::Iterator::Iterator(const typename Vector<N, T>::Iterator &it)
  : _elem_it(it._elem_it)
  {
  }

  template<unsigned int N, typename T>
  Vector<N, T>::Iterator::~Iterator()
  {
  }



/******************************************************************************/
/*!
  \brief
    equality operator for vector iterators

  \param rhs
    the iterator to compare to

  \return
    are the iterators equal?
*/
/******************************************************************************/
  template<unsigned int N, typename T>
  bool Vector<N, T>::Iterator::operator==(const typename Vector<N, T>::Iterator &rhs)
  {
    return _elem_it == rhs._elem_it;
  }


/******************************************************************************/
/*!
  \brief
    less-than operator for vector iterators. Less is defined as being "before"
    the other iterator in the array.

  \param rhs
    the iterator to compare to

  \return
    is rhs less than *this?
*/
/******************************************************************************/
  template<unsigned int N, typename T>
  bool Vector<N, T>::Iterator::operator<(const typename Vector<N, T>::Iterator &rhs)
  {
    return _elem_it < rhs._elem_it;
  }


/******************************************************************************/
/*!
  \brief
    inequality operator for vector iterators

  \param lhs
    one of the iterators to compare

  \param rhs
    the other iterator to compare

  \return
    are lhs and rhs unequal?
*/
/******************************************************************************/
  template<unsigned int N, typename T>
  bool operator!=(const VEC_IT &lhs, const VEC_IT &rhs)
  {
    return !(lhs == rhs);
  }


/******************************************************************************/
/*!
  \brief
    greater-than operator for vector iterators

  \param lhs
    one of the iterators to compare

  \param rhs
    the other itrator to compare

  \return
    is lhs greater than rhs?
*/
/******************************************************************************/
  template<unsigned int N, typename T>
  bool operator>(const VEC_IT &lhs, const VEC_IT &rhs)
  {
    return (!(lhs < rhs) && !(lhs == rhs));
  }


/******************************************************************************/
/*!
  \brief
    less-or-equal operator for vector iterators

  \param lhs
    one of the iterators to compare

  \param rhs
    the other iterator to compare

  \return
    is lhs less than or equal to rhs?
*/
/******************************************************************************/
  template<unsigned int N, typename T>
  bool operator<=(const VEC_IT &lhs, const VEC_IT &rhs)
  {
    return !(lhs > rhs);
  }


/******************************************************************************/
/*!
  \brief
    greater-or-equal operator for vector iterators

  \param lhs
    one of the iterators to compare

  \param rhs
    the other iterator to compare

  \return
    is lhs greater than or equal to rhs?
*/
/******************************************************************************/
  template<unsigned int N, typename T>
  bool operator>=(const VEC_IT &lhs, const VEC_IT &rhs)
  {
    return (!(lhs < rhs));
  }


/******************************************************************************/
/*!
  \brief
    pre-increment for vector iterator

  \return
    a reference to the iterator after incrementing
*/
/******************************************************************************/
  template<unsigned int N, typename T>
  VEC_IT &Vector<N, T>::Iterator::operator++(void)
  {
    ++_elem_it;
    return *this;
  }



/******************************************************************************/
/*!
  \brief
    post-increment for vector iterator

  \return
    a copy of the iterator before incrementing
*/
/******************************************************************************/
  template<unsigned int N, typename T>
  VEC_IT Vector<N, T>::Iterator::operator++(int)
  {
    VEC_IT ret(*this);
    ++_elem_it;
    return ret;
  }


/******************************************************************************/
/*!
  \brief
    pre-decrement for vector iterator

  \return
    a reference to the iterator after decrementing
*/
/******************************************************************************/
  template<unsigned int N, typename T>
  VEC_IT &Vector<N, T>::Iterator::operator--(void)
  {
    --_elem_it;
    return *this;
  }



/******************************************************************************/
/*!
  \brief
    post-decrement operator for vector iterator

  \return
    a copy of the iterator before decrementing
*/
/******************************************************************************/
  template<unsigned int N, typename T>
  VEC_IT Vector<N, T>::Iterator::operator--(int)
  {
    VEC_IT ret(*this);
    --_elem_it;
    return ret;
  }


/******************************************************************************/
/*!
  \brief
    assignment for vector iterators

  \param rhs
    the vector iterator we want to assign this one to be equal to

  \return
    a reference to *this after assignment, so assignment chaining is possible
*/
/******************************************************************************/
  template<unsigned int N, typename T>
  VEC_IT &Vector<N, T>::Iterator::operator=(const Vector<N, T>::Iterator &rhs)
  {
    _elem_it = rhs._elem_it;
    return *this;
  }



/******************************************************************************/
/*!
  \brief
    compound assignment/addition for vector iterators

  \param rhs
    an integral value to be added to the iterator

  \return
    a reference to *this after assignment, so assignment chaining is possible
*/
/******************************************************************************/
  template<unsigned int N, typename T>
  VEC_IT &Vector<N, T>::Iterator::operator+=(const int rhs)
  {
    _elem_it += rhs;
    return *this;
  }



/******************************************************************************/
/*!
  \brief
    compound assignment/subtraction for vector iterators

  \param rhs
    an integral value to be subtracted from the iterator

  \return
    a reference to *this after assignment, so assignment chaining is possible
*/
/******************************************************************************/
  template<unsigned int N, typename T>
  VEC_IT &Vector<N, T>::Iterator::operator-=(const int rhs)
  {
    _elem_it -= rhs;
    return *this;
  }


/******************************************************************************/
/*!
  \brief
    vector iterator-from-iterator subtraction

  \param rhs
    the iterator to subtract from this one

  \return
    the distance between the iterators
*/
/******************************************************************************/
  template<unsigned int N, typename T>
  int Vector<N, T>::Iterator::operator-(const Vector<N, T>::Iterator &rhs)
  {
    return _elem_it - rhs._elem_it;
  }


/******************************************************************************/
/*!
  \brief
    integer addition for vector iterators, with the integral parameter on the
    right hand side.

  \param lhs
    the iterator to offset from

  \param rhs
    the amount to offset by

  \return
    an iterator offset by rhs, from a starting point equal to lhs
*/
/******************************************************************************/
  template<unsigned int N, typename T>
  VEC_IT operator+(const VEC_IT &lhs, const int rhs)
  {
    VEC_IT ret(lhs);
    ret += rhs;
    return ret;
  }


/******************************************************************************/
/*!
  \brief
    integer addition for vector iterators, with the integral parameter on the
    left hand side.

  \param lhs
    the amount to offset by

  \param rhs
    the iterator to offset from

  \return
    an iterator offset by lhs, from a starting point equal to rhs
*/
/******************************************************************************/
  template<unsigned int N, typename T>
  VEC_IT operator+(const int lhs, const VEC_IT &rhs)
  {
    return (rhs + lhs);
  }


/******************************************************************************/
/*!
  \brief
    integer subtraction for vector iterators

  \param lhs
    the iterator to offset from

  \param rhs
    the negative of the amount to offset by

  \return
    an iterator offset by the negation of rhs, from a starting point of lhs
*/
/******************************************************************************/
  template<unsigned int N, typename T>
  VEC_IT operator-(const VEC_IT &lhs, const int rhs)
  {
    return (lhs + (-rhs));
  }


/******************************************************************************/
/*!
  \brief
    dereference operator for vector iterator

  \return
    a reference to the element pointed at by the iterator
*/
/******************************************************************************/
  template<unsigned int N, typename T>
  T &Vector<N, T>::Iterator::operator*(void)
  {
    return *_elem_it;
  }


/******************************************************************************/
/*!
  \brief
    offset dereference for vector iterator

  \param offset
    the amount to offset by

  \return
    a reference to an element (offset) off from the one pointed at by the
    iterator
*/
/******************************************************************************/
  template<unsigned int N, typename T>
  T &Vector<N, T>::Iterator::operator[](const int offset)
  {
    return _elem_it[offset];
  }



}
